import Watcher from "./observe/watcher";
import { createElementVNode, createTextVnode } from "./vdom";

function createElm(vnode) {
  let { tag, data, children, text } = vnode;
  if (typeof tag === "string") {
    //标签
    vnode.el = document.createElement(tag); //这里将真实dom和虚拟dom对应起来

    patchProps(vnode.el, data);
    children.forEach((child) => {
      vnode.el.appendChild(createElm(child));
    });
  } else {
    vnode.el = document.createTextNode(text);
  }
  return vnode.el;
}
function patchProps(el, props) {
  for (let key in props) {
    if (key === "style") {
      for (let styleNmae in props.style) {
        el.style[styleNmae] = props.style[styleNmae];
      }
    } else {
      el.setAttribute(key, props[key]);
    }
  }
}

function patch(oldVNode, vnode) {
  const isRealElement = oldVNode.nodeType;
  if (isRealElement) {
    const elm = oldVNode; //获取真实元素
    const parentElm = elm.parentNode; //拿到父元素
    let newElm = createElm(vnode);
    parentElm.insertBefore(newElm, elm.nextSibling);
    parentElm.removeChild(elm); //删除原来的节点
    return newElm;
  } else {
    // diff算法
  }
}

export function initLifeCycle(Vue) {
  // 将虚拟dom 转换成 真实dom
  Vue.prototype._update = function (vnode) {
    const vm = this;
    const el = vm.$el;
    // patch既有初始化的功能 又有更新的功能
    vm.$el = patch(el, vnode);
  };
  // _c('div',{属性},...children)
  Vue.prototype._c = function () {
    return createElementVNode(this, ...arguments);
  };
  // _v(text)
  Vue.prototype._v = function () {
    return createTextVnode(this, ...arguments);
  };
  Vue.prototype._s = function (value) {
    if (typeof value !== "object") return value;
    return JSON.stringify(value);
  };
  Vue.prototype._render = function () {
    // 当渲染的时候回去实例中取值，我们就可以将属性和视图绑定在一起
    return this.$options.render.call(this);
  };
}

export function mountComponent(vm, el) {
  //这里的el是通过querySelector处理过的
  vm.$el = el;
  // 1.调用render方法产生虚拟dom
  const updateComponent = () => {
  vm._update(vm._render());
  };
  const watcher = new Watcher(vm, updateComponent, true);
  // 2.根据虚拟dom产生真实dom
  // console.log(watcher);
  // 3.插入到el元素中
}

// vue核心流程
// 1、创造响应式数据
// 2、模板转换成ast语法树
// 3、将ast语法树转换成render函数
// 4、后续每次数据更新只执行render函数(无需再执行ast转化的过程)
// 5、render函数会去产生虚拟节点(使用响应式数据)
// 6、根据生成的虚拟dom生成真实dom
